package com.myway.utils.i18n;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

/**
 * 类名称:CnToSpell <br/>
 * 类描述:TODO <br/>
 * 创建时间:2016年4月27日 下午4:15:09 <br/>
 * @author Toby
 * @version V1.0
 * @see CnToSpellMap
 */
public class CnToSpell {
	private static final Logger log = Logger.getLogger(CnToSpell.class);
	
	private static LinkedHashMap<String, String> spellMap = null;

	static {
		if (spellMap == null) {
			spellMap = CnToSpellMap.getSpellMap();
		}
	}

	/**
	 * 获得单个汉字的Ascii，并用"-"连接成一个字符串
	 * 
	 * @param cn char 汉字字符
	 * @return string 错误返回 空字符串,否则返回ascii
	 */
	protected static String getCnAscii(char cn) {
		byte[] bytes = (String.valueOf(cn)).getBytes();
		//log.debug("Byte length of " + cn + ": " + bytes.length);
		if (bytes == null || bytes.length > 2 || bytes.length <= 0) { // 错误
			return "";
		}
		if (bytes.length == 1) { // 英文字符
			return new String(bytes);
		}
		if (bytes.length == 2) { // 中文字符
			int hightByte = 256 + bytes[0];
			int lowByte = 256 + bytes[1];

			String ascii = hightByte + "-" + lowByte;

			//log.debug("ASCII value of " + cn + ": " + ascii);

			return ascii;
		}

		return ""; // 错误
	}

	/**
	 * 根据ASCII码连接成的字符串到SpellMap中查找对应的拼音
	 * 
	 * @param ascii 字符对应的ASCII连接的字符串
	 * @return String 拼音,首先判断是否是中文如果是英文直接返回字符，如果是中文返回拼音,
	 * 
	 * 否则到SpellMap中查找,如果没有找到拼音,则返回null,如果找到则返回拼音.
	 */
	protected static String getSpellByAscii(String ascii) {
		if (ascii.indexOf("-") > -1)
		{
			return (String)spellMap.get(ascii);
		} else {
			return ascii;
		}
	}

	/**
	 * 返回字符串的全拼,是汉字转化为全拼,其它字符不进行转。

	 * 如果字符有多种读音，会以逗号分隔读音。

	 * 请看getFirstFullSpell()

	 * 
	 * @param cnStr String字符串

	 * @return String 转换成全拼后的字符串
	 */
	public static String getFullSpell(String cnStr)
	{
		if (null == cnStr || "".equals(cnStr.trim())) {
			return cnStr;
		}

		char[] chars = cnStr.toCharArray();
		StringBuffer retuBuf = new StringBuffer();
		for (int i = 0, Len = chars.length; i < Len; i++) {
			String ascii = getCnAscii(chars[i]);
			if (ascii.length() == 0) { // 取ascii时出错

				retuBuf.append(chars[i]);
			} else {
				String spell = getSpellByAscii(ascii);
				if (spell == null) {
					retuBuf.append(chars[i]);
				} else {
					retuBuf.append(spell);
				} // end of if spell == null
			} // end of if ascii <= -20400
		} // end of for

		return retuBuf.toString();
	}
	
	public static String getFirstFullSpell(String cnStr)
	{
		if (null == cnStr || "".equals(cnStr.trim())) {
			return cnStr;
		}

		char[] chars = cnStr.toCharArray();
		StringBuffer retuBuf = new StringBuffer();
		for (int i = 0, Len = chars.length; i < Len; i++) {
			String ascii = getCnAscii(chars[i]);
			if (ascii.length() == 0) { // 取ascii时出错


				retuBuf.append(chars[i]);
			} else {
				String spell = getSpellByAscii(ascii);
				if (spell == null) {
					retuBuf.append(chars[i]);
				} else {
					int index = spell.indexOf(",");
					if(index>=0){
						spell = spell.substring(0, index);
					}
					retuBuf.append(spell);
				} // end of if spell == null
			} // end of if ascii <= -20400
		} // end of for

		return retuBuf.toString();
	}
	
	/**
	 * 返回字符串的全拼,是汉字转化为全拼,其它字符不进行转换

	 * This method supports multiple PinYin of Chinese character.
	 * List of all possible PinYin for the given Chinese characters will be returned.
	 * 
	 * @param cnStr
	 * @return
	 */
	public static List<String> getFullSpellList(String cnStr)
	{
		List<String> resultList = new ArrayList<String>();
		
		if (null == cnStr || "".equals(cnStr.trim())) {
			resultList.add(cnStr);
			return resultList;
		}
		
		char[] chars = cnStr.toCharArray();
		StringBuffer retuBuf = new StringBuffer();
		for (int i = 0, Len = chars.length; i < Len; i++) {
			String ascii = getCnAscii(chars[i]);
			if (ascii.length() == 1) { // 取ascii时出错

				retuBuf.append(chars[i]);
			} else {
				String spell = getSpellByAscii(ascii);
				if (spell == null) {
					retuBuf.append(chars[i]);
				} else {
					StringTokenizer pyTkn = new StringTokenizer(spell, ",");
					int pyCount = pyTkn.countTokens();

					if (pyCount > 1) {
						// The current character has more than 1 PinYin

						// Recursive call to get the list of spell for the
						// subsequence string.
						List<String> innerList = getFullSpellList(cnStr
								.substring(i + 1));
						
						String front = retuBuf.toString();
						while (pyTkn.hasMoreTokens()) {
							// For each PinYin of the current character, append with
							// the spelling of the subsequence string.
							String py = pyTkn.nextToken();
							for (String inner : innerList) {
								resultList.add(front + py + inner);
							}
						}

						return resultList;
					} else {
						// The current character has only 1 PinYin.					
						retuBuf.append(spell);
					}
				}
				
			} // end of if ascii <= -20400
		} // end of for
		
		resultList.add(retuBuf.toString());
		return resultList;
	}

	/**
	 * 获取汉语字符串的声母组合，每个汉字取拼音的第一个字符组成的一个字符串
	 * @param cnStr 汉字的字符串
	 * @return 每个汉字拼音的第一个字母所组成的汉字

	 */
	public static String getFirstSpell(String cnStr)
	{
		if (null == cnStr || "".equals(cnStr.trim())) {
			return cnStr;
		}

		char[] chars = cnStr.toCharArray();
		StringBuffer retuBuf = new StringBuffer();
		for (int i = 0, Len = chars.length; i < Len; i++) {
			String ascii = getCnAscii(chars[i]);
			if (ascii.length() == 1) { // 取ascii时出错

				retuBuf.append(chars[i]);
			} else {
				
				/*
				 * Stanley, 12 Oct 2007 
				 * The modification below is required in
				 * order to support chinese character with multiple PinYin (ex:
				 * 乐、重). 
				 * This modification is not being used because this will
				 * add more complexity when performing search and match
				 */
				/* Modification Begin */
				/*
				String fullSpell = getSpellByAscii(ascii);
				StringTokenizer strTkn = new StringTokenizer(fullSpell, ",");
				StringBuffer spellBuffer = new StringBuffer();
				if (strTkn.hasMoreTokens()) {
					spellBuffer.append(strTkn.nextToken().substring(0, 1));
					while (strTkn.hasMoreTokens()) {
						spellBuffer.append(",");
						spellBuffer.append(strTkn.nextToken().substring(0, 1));
					}
				}
				String spell = spellBuffer.toString();
				*/
				/* Modification End */
				
				/*
				 * Original code. Remove the line below if the modification
				 * above is being used.
				 */
				String spell = getSpellByAscii(ascii).substring(0, 1);
				
				
				if (spell == null) {
					retuBuf.append(chars[i]);
				} else {
					retuBuf.append(spell);
				} // end of if spell == null
			} // end of if ascii <= -20400
		} // end of for
		return retuBuf.toString();
	}
	
	/**
	 * 获取汉语字符串的声母组合，每个汉字取拼音的第一个字符组成的一个字符串
	 * This method supports multiple PinYin of Chinese character.
	 * List of all possible PinYin for the given Chinese characters will be returned.
	 * 
	 * @param cnStr
	 * @return
	 */
	public static List<String> getFirstSpellList(String cnStr)
	{
		List<String> resultList = new ArrayList<String>();
		
		if (null == cnStr || "".equals(cnStr.trim())) {
			resultList.add(cnStr);
			return resultList;
		}
		
		char[] chars = cnStr.toCharArray();
		StringBuffer retuBuf = new StringBuffer();
		for (int i = 0, Len = chars.length; i < Len; i++) {
			String ascii = getCnAscii(chars[i]);
			if (ascii.length() == 1) { // 取ascii时出错

				retuBuf.append(chars[i]);
			} else {
				String fullSpell = getSpellByAscii(ascii);
				if (fullSpell == null) {
					retuBuf.append(chars[i]);
				} else {
					
					StringTokenizer pyTkn = new StringTokenizer(fullSpell, ",");
					int pyCount = pyTkn.countTokens();
					if (pyCount > 1) {
						// The current character has more than 1 PinYin
	
						// Recursive call to get the list of spell for the
						// subsequence string.
						List<String> innerList = getFirstSpellList(cnStr
								.substring(i + 1));
						
						String front = retuBuf.toString();
						while (pyTkn.hasMoreTokens()) {
							// For each PinYin of the current character, append with
							// the spelling of the subsequence string.
							String py = pyTkn.nextToken();
							for (String inner : innerList) {
								resultList.add(front + py.substring(0, 1) + inner);
							}
						}
	
						return resultList;
					} else {
						// The current character has only 1 PinYin.
						retuBuf.append(fullSpell.substring(0, 1));
					}
					
				}
			} // end of if ascii <= -20400
		} // end of for
		
		resultList.add(retuBuf.toString());
		return resultList;
	}

	public static void main(String[] args) {
		Date start = new Date();
		String str = null;
		str = "逯闫乐";
		String pinyin = CnToSpell.getFirstFullSpell(str);
		log.debug("Spell=" + pinyin);
		log.debug("Spell=" + CnToSpell.getFullSpell(str));

		str = "许金锁";
		log.debug("str: " + CnToSpell.getFirstFullSpell(str));
		log.debug("Full spell: " + getFullSpell(str));
		log.debug("First full spell: " + getFirstFullSpell(str));	

	}
}